package marcis.jarina;

import marcis.jarina.directory.DirectoryWalker;
import marcis.jarina.directory.FileActionListener;
import marcis.jarina.directory.MyFileFilter;
import marcis.jarina.directory.pom.PomProcessor;
import marcis.jarina.directory.repository.FasterJarProcessor;
import marcis.jarina.hibernate.dao.ArchiveDao;
import marcis.jarina.hibernate.dao.JavaClassDao;
import marcis.jarina.hibernate.entities.Archive;
import marcis.jarina.hibernate.entities.JavaClass;
import marcis.stopwatch.SimpleWatch;
import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Component;

import java.io.File;
import java.util.ArrayList;
import java.util.List;


@Component
public class DBFacade {

    private static final Logger log = Logger.getLogger(DBFacade.class);

    private final SimpleWatch simpleWatch = new SimpleWatch();

    @Autowired
    @Qualifier(value = "archiveDao")
    private ArchiveDao archiveDao;

    @Autowired
    @Qualifier(value = "classDao")
    private JavaClassDao classDao;

    @Autowired
    private PomProcessor pomProcessor;

    public void messagePause(String message) {
        //display messgae
        log.info(message);

        //pause
        try {
            Thread.sleep(4000);
        } catch (InterruptedException e) {
            log.error("Thread was interupted!");
            return;
        }

    }

    public void storeRepositoryInfoToDatabase() {
        simpleWatch.press("fill archive table");
        storeArchiveCommonInfo();
        simpleWatch.press("fill archive table");

        simpleWatch.press("fill javaclass table");
        storeArchiveClasses();
        simpleWatch.press("fill javaclass table");
    }


    private void storeArchiveCommonInfo() {
        MyFileFilter.PredicateFileNameRegex predicate = new MyFileFilter.PredicateFileNameRegex(".*\\.pom");
        MyFileFilter pomFilter = new MyFileFilter(predicate);

        DirectoryWalker directoryWalker = new DirectoryWalker(pomProcessor.getRepositoryDir(), pomFilter);
        directoryWalker.addListener(pomProcessor);
        directoryWalker.doSearch();
        // save last unsaved archives
        //pomProcessor.finish();
        directoryWalker.finish();
    }


    private void storeArchiveClasses() {
        FileActionListener fasterJarProcessor = new FasterJarProcessor();
        final int fetchedEntries = 50;
        int page = 0;
        while (page * fetchedEntries < archiveDao.getTotalCount()) {
            List<Archive> archives = archiveDao.pagedFilter(null, null, Archive.class,
                    page * fetchedEntries, fetchedEntries);
            log.info("Start processing next " + archives.size() + " from database!");
            for (Archive archive : archives) {
                if (archive.getFilePath() != null) {
                    // message producer for jarprocessor
                    fasterJarProcessor.onFileFound(new File(archive.getFilePath()));
                    classDao.save(JavaClass.convert(
                            ((FasterJarProcessor) fasterJarProcessor).getEntries(), archive));
                }
            }
            page++;
        }
        log.info("Total " + classDao.filter(null, null).size() + " java classes found in database!");
    }


    public List<File> getRequiredJars(List<String> allImports) {
        List<File> result = new ArrayList<File>();
        log.debug("allImports: " + allImports);
        for (String imp : allImports) {
            List<JavaClass> jc = classDao.filter("fullName", imp);
            if (jc.size() == 1) {
                Archive archive = archiveDao.loadById(jc.get(0).getArchive().getId());
                result.add(new File(archive.getFilePath()));
            } else if (jc.size() > 1) {
                log.warn("There is more than one class found for import! Here you are: " + jc);
                Archive archive = archiveDao.loadById(jc.get(0).getArchive().getId());
                result.add(new File(archive.getFilePath()));
            } else {
                log.warn("No class found for an import: " + imp);
            }
        }
        return result;
    }
}
